home *** CD-ROM | disk | FTP | other *** search
/ STraTOS 1997 April & May / STraTOS 1 - 1997 April & May.iso / CD01 / INTERNET / SITES / LITTLE / P3SRC.ZIP / ATARI / TOKENIZE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-15  |  56.0 KB  |  2,696 lines

  1. /****************************************************************************
  2. *                tokenize.c
  3. *
  4. *  This module implements the first part of a two part parser for the scene
  5. *  description files.  This phase changes the input file into tokens.
  6. *
  7. *  This module tokenizes the input file and sends the tokens created
  8. *  to the parser (the second stage).  Tokens sent to the parser contain a
  9. *  token ID, the line number of the token, and if necessary, some data for
  10. *  the token.
  11. *
  12. *  from Persistence of Vision(tm) Ray Tracer
  13. *  Copyright 1996 Persistence of Vision Team
  14. *---------------------------------------------------------------------------
  15. *  NOTICE: This source code file is provided so that users may experiment
  16. *  with enhancements to POV-Ray and to port the software to platforms other
  17. *  than those supported by the POV-Ray Team.  There are strict rules under
  18. *  which you are permitted to use this file.  The rules are in the file
  19. *  named POVLEGAL.DOC which should be distributed with this file. If
  20. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  21. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  22. *  Forum.  The latest version of POV-Ray may be found there as well.
  23. *
  24. * This program is based on the popular DKB raytracer version 2.12.
  25. * DKBTrace was originally written by David K. Buck.
  26. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  27. *
  28. *****************************************************************************/
  29.  
  30. #include <ctype.h>
  31. #include "frame.h"
  32. #include "povray.h"
  33. #include "povproto.h"
  34. #include "parse.h"
  35. #include "povray.h"
  36. #include "render.h"
  37. #include "tokenize.h"
  38. #include "express.h"
  39.  
  40.  
  41.  
  42. /*****************************************************************************
  43. * Local preprocessor defines
  44. ******************************************************************************/
  45.  
  46.  
  47.  
  48. /*****************************************************************************
  49. * Local typedefs
  50. ******************************************************************************/
  51.  
  52. #define MAX_INCLUDE_FILES 10
  53.  
  54. #define CALL(x) { if (!(x)) return (FALSE); }
  55.  
  56. #define COND_STACK_SIZE 200
  57.  
  58. typedef enum cond_type
  59. {
  60.   ROOT_COND=0,
  61.   WHILE_COND,
  62.   IF_TRUE_COND,
  63.   IF_FALSE_COND,
  64.   ELSE_COND,
  65.   SWITCH_COND,
  66.   CASE_TRUE_COND,
  67.   CASE_FALSE_COND,
  68.   SKIP_TIL_END_COND
  69. } COND_TYPE;
  70.  
  71.  
  72. typedef struct Reserved_Word_Struct RESERVED_WORD;
  73.  
  74. #define HASH_TABLE_SIZE 257
  75.  
  76. typedef struct Hash_Table_Struct HASH_TABLE;
  77.  
  78. struct Hash_Table_Struct
  79. {
  80.   RESERVED_WORD Entry;
  81.   HASH_TABLE *next;
  82. };
  83.  
  84.  
  85.  
  86.  
  87. /*****************************************************************************
  88. * Local variables
  89. ******************************************************************************/
  90.  
  91. /* Hash tables */
  92.  
  93. HASH_TABLE *Reserved_Words_Hash_Table[HASH_TABLE_SIZE];
  94. HASH_TABLE *Symbol_Table_Hash_Table[HASH_TABLE_SIZE];
  95.  
  96. int Max_Symbols, Max_Constants;
  97.  
  98. static int String_Index;
  99. char String[MAX_STRING_INDEX];
  100. char String2[MAX_STRING_INDEX];
  101.  
  102. int Number_Of_Constants;
  103.  
  104. /* moved here to allow reinitialization */
  105.  
  106. static int token_count = 0, line_count = 10;
  107.  
  108. static int Number_Of_Symbols;
  109. struct Constant_Struct *Constants;
  110.  
  111. static int Include_File_Index;
  112. static DATA_FILE *Data_File;
  113. static DATA_FILE Include_Files[MAX_INCLUDE_FILES];
  114.  
  115. struct Token_Struct Token;
  116.  
  117. static char **Echo_Buff;
  118. static char  *Echo_Ptr;
  119. static int    Echo_Indx;
  120. static int    Echo_Line;
  121. static int    Echo_Unget_Flag;
  122. static int    Echo_Unget_Char;
  123.  
  124. typedef struct Cond_Stack_Entry CS_ENTRY;
  125.  
  126. struct Cond_Stack_Entry
  127. {
  128.   COND_TYPE Cond_Type;
  129.   DBL Switch_Value;
  130.   FILE *While_File;
  131.   long While_Pos,While_Line_No;
  132. };
  133.  
  134. static CS_ENTRY *Cond_Stack;
  135. static int CS_Index, Skipping, Inside_Ifdef;
  136.  
  137. int input_file_in_memory = 0 ;
  138.  
  139. /*
  140.  * Here are the reserved words.  If you need to add new words,
  141.  * be sure to declare them in parse.h
  142.  */
  143.  
  144. RESERVED_WORD Reserved_Words [LAST_TOKEN] = {
  145.   {AA_LEVEL_TOKEN, "aa_level"},
  146.   {AA_THRESHOLD_TOKEN, "aa_threshold"},
  147.   {ABS_TOKEN, "abs"},
  148.   {ACOS_TOKEN, "acos"},
  149.   {ACOSH_TOKEN,"acosh"},
  150.   {ADAPTIVE_TOKEN, "adaptive"},
  151.   {ADC_BAILOUT_TOKEN, "adc_bailout"},
  152.   {AGATE_TOKEN, "agate"},
  153.   {AGATE_TURB_TOKEN, "agate_turb"},
  154.   {ALL_TOKEN, "all"},
  155.   {ALPHA_TOKEN, "alpha"},
  156.   {AMBIENT_LIGHT_TOKEN, "ambient_light"},
  157.   {AMBIENT_TOKEN, "ambient"},
  158.   {AMPERSAND_TOKEN, "&"},
  159.   {ANGLE_TOKEN, "angle"},
  160.   {APERTURE_TOKEN, "aperture"},
  161.   {ARC_ANGLE_TOKEN, "arc_angle"},
  162.   {AREA_LIGHT_TOKEN, "area_light"},
  163.   {ASC_TOKEN, "asc"},
  164.   {ASIN_TOKEN, "asin"},
  165.   {ASINH_TOKEN,"asinh"},
  166.   {ASSUMED_GAMMA_TOKEN, "assumed_gamma"},
  167.   {ATAN_TOKEN,"atan"},
  168.   {ATAN2_TOKEN,"atan2"},
  169.   {ATANH_TOKEN,"atanh"},
  170.   {ATMOSPHERE_ID_TOKEN, "atmosphere identifier"},
  171.   {ATMOSPHERE_TOKEN, "atmosphere"},
  172.   {ATMOSPHERIC_ATTENUATION_TOKEN, "atmospheric_attenuation"},
  173.   {ATTENUATING_TOKEN, "attenuating"},
  174.   {AT_TOKEN, "@"},
  175.   {AVERAGE_TOKEN, "average"},
  176.   {BACKGROUND_TOKEN, "background"},
  177.   {BACK_QUOTE_TOKEN, "`"},
  178.   {BACK_SLASH_TOKEN, "\\"},
  179.   {BAR_TOKEN, "|"},
  180.   {BICUBIC_PATCH_TOKEN, "bicubic_patch"},
  181.   {BLACK_HOLE_TOKEN, "black_hole"},
  182.   {BLOB_TOKEN, "blob"},
  183.   {BLUE_TOKEN, "blue"},
  184.   {BLUR_SAMPLES_TOKEN, "blur_samples"},
  185.   {BOUNDED_BY_TOKEN, "bounded_by"},
  186.   {BOX_MAPPING_TOKEN, "box_mapping"},
  187.   {BOX_TOKEN, "box"},
  188.   {BOZO_TOKEN, "bozo"},
  189.   {BREAK_TOKEN, "break"},
  190.   {BRICK_SIZE_TOKEN, "brick_size"},
  191.   {BRICK_TOKEN, "brick"},
  192.   {BRIGHTNESS_TOKEN, "brightness" },
  193.   {BRILLIANCE_TOKEN, "brilliance"},
  194.   {BUMPS_TOKEN, "bumps"},
  195.   {BUMPY1_TOKEN, "bumpy1"},
  196.   {BUMPY2_TOKEN, "bumpy2"},
  197.   {BUMPY3_TOKEN, "bumpy3"},
  198.   {BUMP_MAP_TOKEN, "bump_map"},
  199.   {BUMP_SIZE_TOKEN, "bump_size"},
  200.   {CAMERA_ID_TOKEN, "camera identifier"},
  201.   {CAMERA_TOKEN, "camera"},
  202.   {CASE_TOKEN, "case"},
  203.   {CAUSTICS_TOKEN, "caustics"},
  204.   {CEIL_TOKEN, "ceil"},
  205.   {CHECKER_TOKEN, "checker"},
  206.   {CHR_TOKEN, "chr"},
  207.   {CLIPPED_BY_TOKEN, "clipped_by"},
  208.   {CLOCK_TOKEN,"clock"},
  209.   {COLON_TOKEN, ":"},
  210.   {COLOUR_ID_TOKEN, "colour identifier"},
  211.   {COLOUR_KEY_TOKEN,"color keyword"},
  212.   {COLOUR_MAP_ID_TOKEN, "colour map identifier"},
  213.   {COLOUR_MAP_TOKEN, "color_map"},
  214.   {COLOUR_MAP_TOKEN, "colour_map"},
  215.   {COLOUR_TOKEN, "color"},
  216.   {COLOUR_TOKEN, "colour"},
  217.   {COMMA_TOKEN, ","},
  218.   {COMPONENT_TOKEN, "component"},
  219.   {COMPOSITE_TOKEN, "composite"},
  220.   {CONCAT_TOKEN, "concat"},
  221.   {CONE_TOKEN, "cone"},
  222.   {CONFIDENCE_TOKEN, "confidence"},
  223.   {CONIC_SWEEP_TOKEN, "conic_sweep"},
  224.   {CONSTANT_TOKEN,"constant"},
  225.   {CONTROL0_TOKEN,"control0"},
  226.   {CONTROL1_TOKEN,"control1"},
  227.   {COS_TOKEN,"cos"},
  228.   {COSH_TOKEN,"cosh"},
  229.   {COUNT_TOKEN, "count" },
  230.   {CRACKLE_TOKEN, "crackle"},
  231.   {CRAND_TOKEN, "crand"},
  232.   {CUBE_TOKEN, "cube"},
  233.   {CUBIC_SPLINE_TOKEN, "cubic_spline"},
  234.   {CUBIC_TOKEN, "cubic"},
  235.   {CYLINDER_TOKEN, "cylinder"},
  236.   {CYLINDRICAL_MAPPING_TOKEN, "cylindrical_mapping"},
  237.   {DASH_TOKEN, "-"},
  238.   {DEBUG_TOKEN, "debug"},
  239.   {DECLARE_TOKEN, "declare"},
  240.   {DEFAULT_TOKEN, "default"},
  241.   {DEGREES_TOKEN, "degrees"},
  242.   {DENTS_TOKEN, "dents"},
  243.   {DIFFERENCE_TOKEN, "difference"},
  244.   {DIFFUSE_TOKEN, "diffuse"},
  245.   {DIRECTION_TOKEN, "direction"},
  246.   {DISC_TOKEN, "disc"},
  247.   {DISTANCE_MAXIMUM_TOKEN, "distance_maximum" },
  248.   {DISTANCE_TOKEN, "distance"},
  249.   {DIV_TOKEN, "div"},
  250.   {DOLLAR_TOKEN, "$"},
  251.   {DUST_TOKEN, "dust"},
  252.   {DUST_TYPE_TOKEN, "dust_type"},
  253.   {ELSE_TOKEN, "else"},
  254.   {EMITTING_TOKEN, "emitting"},
  255.   {END_OF_FILE_TOKEN, "End of File"},
  256.   {END_TOKEN, "end"},
  257.   {EQUALS_TOKEN, "="},
  258.   {ERROR_BOUND_TOKEN, "error_bound" },
  259.   {ERROR_TOKEN, "error"},
  260.   {ECCENTRICITY_TOKEN, "eccentricity"},
  261.   {EXCLAMATION_TOKEN, "!"},
  262.   {EXPONENT_TOKEN, "exponent"},
  263.   {EXP_TOKEN,"exp"},
  264.   {FADE_DISTANCE_TOKEN, "fade_distance"},
  265.   {FADE_POWER_TOKEN, "fade_power"},
  266.   {FALLOFF_ANGLE_TOKEN, "falloff_angle"},
  267.   {FALLOFF_TOKEN, "falloff"},
  268.   {FALSE_TOKEN, "false"},
  269.   {FILE_EXISTS_TOKEN, "file_exists"},
  270.   {FILL_LIGHT_TOKEN, "shadowless"},
  271.   {FILTER_TOKEN, "filter"},
  272.   {FINISH_ID_TOKEN, "finish identifier"},
  273.   {FINISH_TOKEN, "finish"},
  274.   {FISHEYE_TOKEN, "fisheye"},
  275.   {FLATNESS_TOKEN, "flatness"},
  276.   {FLIP_TOKEN, "flip"},
  277.   {FLOAT_FUNCT_TOKEN,"float function"},
  278.   {FLOAT_ID_TOKEN, "float identifier"},
  279.   {FLOAT_TOKEN, "float constant"},
  280.   {FLOOR_TOKEN, "floor"},
  281.   {FOCAL_POINT_TOKEN, "focal_point"},
  282.   {FOG_ALT_TOKEN, "fog_alt"},
  283.   {FOG_ID_TOKEN, "fog identifier"},
  284.   {FOG_OFFSET_TOKEN, "fog_offset"},
  285.   {FOG_TOKEN, "fog"},
  286.   {FOG_TYPE_TOKEN, "fog_type"},
  287.   {FREQUENCY_TOKEN, "frequency"},
  288.   {GIF_TOKEN, "gif"},
  289.   {GLOBAL_SETTINGS_TOKEN, "global_settings" },
  290.   {GLOWING_TOKEN, "glowing"},
  291.   {GRADIENT_TOKEN, "gradient"},
  292.   {GRANITE_TOKEN, "granite"},
  293.   {GRAY_THRESHOLD_TOKEN, "gray_threshold" },
  294.   {GREEN_TOKEN, "green"},
  295.   {HALO_ID_TOKEN, "halo identifier"},
  296.   {HALO_TOKEN, "halo"},
  297.   {HASH_TOKEN, "#"},
  298.   {HAT_TOKEN, "^"},
  299.   {HEIGHT_FIELD_TOKEN, "height_field"},
  300.   {HEXAGON_TOKEN, "hexagon"},
  301.   {HF_GRAY_16_TOKEN, "hf_gray_16" },
  302.   {HIERARCHY_TOKEN, "hierarchy"},
  303.   {HOLLOW_TOKEN, "hollow"},
  304.   {HYPERCOMPLEX_TOKEN, "hypercomplex"},
  305.   {IDENTIFIER_TOKEN, "undeclared identifier"},
  306.   {IFDEF_TOKEN, "ifdef"},
  307.   {IFNDEF_TOKEN, "ifndef"},
  308.   {IFF_TOKEN, "iff"},
  309.   {IF_TOKEN, "if"},
  310.   {IMAGE_MAP_TOKEN, "image_map"},
  311.   {INCIDENCE_TOKEN, "incidence"},
  312.   {INCLUDE_TOKEN, "include"},
  313.   {INTERPOLATE_TOKEN, "interpolate"},
  314.   {INTERSECTION_TOKEN, "intersection"},
  315.   {INT_TOKEN,"int"},
  316.   {INVERSE_TOKEN, "inverse"},
  317.   {IOR_TOKEN, "ior"},
  318.   {IRID_TOKEN, "irid"},
  319.   {IRID_WAVELENGTH_TOKEN,"irid_wavelength"},
  320.   {JITTER_TOKEN, "jitter"},
  321.   {JULIA_FRACTAL_TOKEN, "julia_fractal"},
  322.   {LAMBDA_TOKEN, "lambda"},
  323.   {LATHE_TOKEN, "lathe"},
  324.   {LEFT_ANGLE_TOKEN, "<"},
  325.   {LEFT_CURLY_TOKEN, "{"},
  326.   {LEFT_PAREN_TOKEN, "("},
  327.   {LEFT_SQUARE_TOKEN, "["},
  328.   {LEOPARD_TOKEN, "leopard"},
  329.   {LIGHT_SOURCE_TOKEN, "light_source"},
  330.   {LINEAR_SPLINE_TOKEN, "linear_spline"},
  331.   {LINEAR_SWEEP_TOKEN, "linear_sweep"},
  332.   {LINEAR_TOKEN, "linear"},
  333.   {LOCATION_TOKEN, "location"},
  334.   {LOG_TOKEN,"log"},
  335.   {LOOKS_LIKE_TOKEN, "looks_like"},
  336.   {LOOK_AT_TOKEN, "look_at"},
  337.   {LOW_ERROR_FACTOR_TOKEN, "low_error_factor" },
  338.   {MANDEL_TOKEN,"mandel"},
  339.   {MAP_TYPE_TOKEN, "map_type"},
  340.   {MARBLE_TOKEN, "marble"},
  341.   {MATERIAL_MAP_TOKEN, "material_map"},
  342.   {MATRIX_TOKEN, "matrix"},
  343.   {MAX_INTERSECTIONS, "max_intersections"},
  344.   {MAX_ITERATION_TOKEN, "max_iteration"},
  345.   {MAX_TOKEN, "max"},
  346.   {MAX_TRACE_LEVEL_TOKEN, "max_trace_level"},
  347.   {MAX_VALUE_TOKEN, "max_value"},
  348.   {MERGE_TOKEN,"merge"},
  349.   {MESH_TOKEN, "mesh"},
  350.   {METALLIC_TOKEN, "metallic"},
  351.   {MINIMUM_REUSE_TOKEN, "minimum_reuse" },
  352.   {MIN_TOKEN, "min"},
  353.   {MOD_TOKEN,"mod"},
  354.   {MORTAR_TOKEN, "mortar"},
  355.   {NEAREST_COUNT_TOKEN, "nearest_count" },
  356.   {NORMAL_MAP_ID_TOKEN,"normal_map identifier"},
  357.   {NORMAL_MAP_TOKEN, "normal_map"},
  358.   {NO_SHADOW_TOKEN, "no_shadow"},
  359.   {NO_TOKEN, "no"},
  360.   {NUMBER_OF_WAVES_TOKEN, "number_of_waves"},
  361.   {OBJECT_ID_TOKEN, "object identifier"},
  362.   {OBJECT_TOKEN, "object"},
  363.   {OCTAVES_TOKEN, "octaves"},
  364.   {OFFSET_TOKEN, "offset"},
  365.   {OFF_TOKEN, "off"},
  366.   {OMEGA_TOKEN, "omega"},
  367.   {OMNIMAX_TOKEN, "omnimax"},
  368.   {ONCE_TOKEN, "once"},
  369.   {ONION_TOKEN, "onion"},
  370.   {ON_TOKEN, "on"},
  371.   {OPEN_TOKEN, "open"},
  372.   {ORTHOGRAPHIC_TOKEN, "orthographic"},
  373.   {PANORAMIC_TOKEN, "panoramic"},
  374.   {PATTERN1_TOKEN, "pattern1"},
  375.   {PATTERN2_TOKEN, "pattern2"},
  376.   {PATTERN3_TOKEN, "pattern3"},
  377.   {PERCENT_TOKEN, "%"},
  378.   {PERIOD_TOKEN, ". (period)"},
  379.   {PERSPECTIVE_TOKEN, "perspective"},
  380.   {PGM_TOKEN, "pgm"},
  381.   {PHASE_TOKEN, "phase"},
  382.   {PHONG_SIZE_TOKEN, "phong_size"},
  383.   {PHONG_TOKEN, "phong"},
  384.   {PIGMENT_ID_TOKEN, "pigment identifier"},
  385.   {PIGMENT_MAP_ID_TOKEN,"pigment_map identifier"},
  386.   {PIGMENT_MAP_TOKEN, "pigment_map"},
  387.   {PIGMENT_TOKEN, "pigment"},
  388.   {PI_TOKEN,"pi"},
  389.   {PLANAR_MAPPING_TOKEN, "planar_mapping"},
  390.   {PLANE_TOKEN, "plane"},
  391.   {PLUS_TOKEN, "+"},
  392.   {PNG_TOKEN, "png"},
  393.   {POINT_AT_TOKEN, "point_at"},
  394.   {POLYGON_TOKEN, "polygon"},
  395.   {POLY_TOKEN, "poly"},
  396.   {POT_TOKEN, "pot"},
  397.   {POW_TOKEN,"pow"},
  398.   {PPM_TOKEN, "ppm"},
  399.   {PRECISION_TOKEN, "precision"},
  400.   {PRISM_TOKEN, "prism"},
  401.   {PWR_TOKEN,"pwr"},
  402.   {QUADRATIC_SPLINE_TOKEN, "quadratic_spline"},
  403.   {QUADRIC_TOKEN, "quadric"},
  404.   {QUARTIC_TOKEN, "quartic"},
  405.   {QUATERNION_TOKEN, "quaternion"},
  406.   {QUESTION_TOKEN, "?"},
  407.   {QUICK_COLOUR_TOKEN,"quick_color"},
  408.   {QUICK_COLOUR_TOKEN,"quick_colour"},
  409.   {QUILTED_TOKEN,"quilted"},
  410.   {RADIAL_TOKEN, "radial"},
  411.   {RADIANS_TOKEN, "radians"},
  412.   {RADIOSITY_TOKEN, "radiosity" },
  413.   {RADIUS_TOKEN, "radius"},
  414.   {RAINBOW_ID_TOKEN, "rainbow identifier"},
  415.   {RAINBOW_TOKEN, "rainbow"},
  416.   {RAMP_WAVE_TOKEN, "ramp_wave"},
  417.   {RAND_TOKEN, "rand"},
  418.   {RANGE_TOKEN, "range"},
  419.   {RECIPROCAL_TOKEN, "reciprocal" },
  420.   {RECURSION_LIMIT_TOKEN, "recursion_limit" },
  421.   {RED_TOKEN, "red"},
  422.   {REFLECTION_TOKEN, "reflection"},
  423.   {REFRACTION_TOKEN, "refraction"},
  424.   {REL_GE_TOKEN,">="},
  425.   {REL_LE_TOKEN,"<="},
  426.   {REL_NE_TOKEN,"!="},
  427.   {RENDER_TOKEN, "render"},
  428.   {REPEAT_TOKEN, "repeat"},
  429.   {RGBFT_TOKEN, "rgbft"},
  430.   {RGBF_TOKEN,"rgbf"},
  431.   {RGBT_TOKEN, "rgbt"},
  432.   {RGB_TOKEN,"rgb"},
  433.   {RIGHT_ANGLE_TOKEN, ">"},
  434.   {RIGHT_CURLY_TOKEN, "}"},
  435.   {RIGHT_PAREN_TOKEN, ")"},
  436.   {RIGHT_SQUARE_TOKEN, "]"},
  437.   {RIGHT_TOKEN, "right"},
  438.   {RIPPLES_TOKEN, "ripples"},
  439.   {ROTATE_TOKEN, "rotate"},
  440.   {ROUGHNESS_TOKEN, "roughness"},
  441.   {SAMPLES_TOKEN, "samples"},
  442.   {SCALE_TOKEN, "scale"},
  443.   {SCALLOP_WAVE_TOKEN, "scallop_wave"},
  444.   {SCATTERING_TOKEN, "scattering"},
  445.   {SEED_TOKEN, "seed"},
  446.   {SEMI_COLON_TOKEN, ";"},
  447.   {SINE_WAVE_TOKEN, "sine_wave"},
  448.   {SINGLE_QUOTE_TOKEN, "'"},
  449.   {SIN_TOKEN,"sin"},
  450.   {SINH_TOKEN,"sinh"},
  451.   {SKYSPHERE_ID_TOKEN, "sky_sphere identifier"},
  452.   {SKYSPHERE_TOKEN, "sky_sphere"},
  453.   {SKY_TOKEN, "sky"},
  454.   {SLASH_TOKEN, "/"},
  455.   {SLICE_TOKEN, "slice"},
  456.   {SLOPE_MAP_ID_TOKEN,"slope_map identifier"},
  457.   {SLOPE_MAP_TOKEN, "slope_map"},
  458.   {SMOOTH_TOKEN,"smooth"},
  459.   {SMOOTH_TRIANGLE_TOKEN, "smooth_triangle"},
  460.   {SOR_TOKEN, "sor"},
  461.   {SPECULAR_TOKEN, "specular"},
  462.   {SPHERE_TOKEN, "sphere"},
  463.   {SPHERICAL_MAPPING_TOKEN, "spherical_mapping"},
  464.   {SPIRAL1_TOKEN, "spiral1"},
  465.   {SPIRAL2_TOKEN, "spiral2"},
  466.   {SPIRAL_TOKEN, "spiral"},
  467.   {SPOTLIGHT_TOKEN, "spotlight"},
  468.   {SPOTTED_TOKEN, "spotted"},
  469.   {SQR_TOKEN,"sqr"},
  470.   {SQRT_TOKEN,"sqrt"},
  471.   {STAR_TOKEN, "*"},
  472.   {STATISTICS_TOKEN, "statistics"},
  473.   {STRCMP_TOKEN, "strcmp"},
  474.   {STRENGTH_TOKEN, "strength"},
  475.   {STRING_ID_TOKEN, "string identifier"},
  476.   {STRING_LITERAL_TOKEN, "string literal"},
  477.   {STRLEN_TOKEN, "strlen"},
  478.   {STRLWR_TOKEN, "strlwr"},
  479.   {STRUPR_TOKEN, "strupr"},
  480.   {STR_TOKEN, "str"},
  481.   {STURM_TOKEN, "sturm"},
  482.   {SUBSTR_TOKEN, "substr"},
  483.   {SUPERELLIPSOID_TOKEN, "superellipsoid"},
  484.   {SWITCH_TOKEN, "switch"},
  485.   {SYS_TOKEN, "sys"},
  486.   {T_TOKEN, "t"},
  487.   {TAN_TOKEN, "tan"},
  488.   {TANH_TOKEN,"tanh"},
  489.   {TEST_CAMERA_1_TOKEN, "test_camera_1"},
  490.   {TEST_CAMERA_2_TOKEN, "test_camera_2"},
  491.   {TEST_CAMERA_3_TOKEN, "test_camera_3"},
  492.   {TEST_CAMERA_4_TOKEN, "test_camera_4"},
  493.   {TEXTURE_ID_TOKEN, "texture identifier"},
  494.   {TEXTURE_MAP_ID_TOKEN,"texture_map identifier"},
  495.   {TEXTURE_MAP_TOKEN, "texture_map"},
  496.   {TEXTURE_TOKEN, "texture"},
  497.   {TEXT_TOKEN, "text"},
  498.   {TGA_TOKEN, "tga"},
  499.   {THICKNESS_TOKEN, "thickness"},
  500.   {THRESHOLD_TOKEN, "threshold"},
  501.   {TIGHTNESS_TOKEN, "tightness"},
  502.   {TILDE_TOKEN, "~"},
  503.   {TILE2_TOKEN, "tile2"},
  504.   {TILES_TOKEN, "tiles"},
  505.   {TNORMAL_ID_TOKEN, "normal identifier"},
  506.   {TNORMAL_TOKEN, "normal"},
  507.   {TORUS_TOKEN, "torus"},
  508.   {TRACK_TOKEN, "track"},
  509.   {TRANSFORM_ID_TOKEN, "transform identifier"},
  510.   {TRANSFORM_TOKEN, "transform"},
  511.   {TRANSLATE_TOKEN, "translate"},
  512.   {TRANSMIT_TOKEN, "transmit"},
  513.   {TRIANGLE_TOKEN, "triangle"},
  514.   {TRIANGLE_WAVE_TOKEN, "triangle_wave"},
  515.   {TRUE_TOKEN, "true"},
  516.   {TTF_TOKEN, "ttf"},
  517.   {TURBULENCE_TOKEN, "turbulence"},
  518.   {TURB_DEPTH_TOKEN, "turb_depth"},
  519.   {TYPE_TOKEN, "type"},
  520.   {ULTRA_WIDE_ANGLE_TOKEN, "ultra_wide_angle"},
  521.   {UNION_TOKEN, "union"},
  522.   {UP_TOKEN, "up"},
  523.   {USE_COLOUR_TOKEN,"use_color"},
  524.   {USE_COLOUR_TOKEN,"use_colour"},
  525.   {USE_INDEX_TOKEN,"use_index"},
  526.   {U_STEPS_TOKEN, "u_steps"},
  527.   {U_TOKEN, "u"},
  528.   {VAL_TOKEN, "val"},
  529.   {VARIANCE_TOKEN, "variance"},
  530.   {VAXIS_ROTATE_TOKEN,"vaxis_rotate"},
  531.   {VCROSS_TOKEN,"vcross"},
  532.   {VDOT_TOKEN,"vdot"},
  533.   {VECTOR_FUNCT_TOKEN,"vector function"},
  534.   {VECTOR_ID_TOKEN, "vector identifier"},
  535.   {VERSION_TOKEN, "version"},
  536.   {VLENGTH_TOKEN,"vlength"},
  537.   {VNORMALIZE_TOKEN,"vnormalize"},
  538.   {VOLUME_OBJECT_TOKEN, "volume_object"},
  539.   {VOLUME_RENDERED_TOKEN, "volume_rendered"},
  540.   {VOL_WITH_LIGHT_TOKEN, "vol_with_light"},
  541.   {VROTATE_TOKEN,"vrotate"},
  542.   {V_STEPS_TOKEN, "v_steps"},
  543.   {V_TOKEN, "v"},
  544.   {WARNING_TOKEN, "warning"},
  545.   {WARP_TOKEN, "warp"},
  546.   {WATER_LEVEL_TOKEN, "water_level"},
  547.   {WAVES_TOKEN, "waves"},
  548.   {WHILE_TOKEN, "while"},
  549.   {WIDTH_TOKEN, "width"},
  550.   {WOOD_TOKEN, "wood"},
  551.   {WRINKLES_TOKEN, "wrinkles"},
  552.   {X_TOKEN,"x"},
  553.   {YES_TOKEN, "yes"},
  554.   {Y_TOKEN,"y"},
  555.   {Z_TOKEN,"z"}
  556. };
  557.  
  558.  
  559.  
  560. /*****************************************************************************
  561. * Static functions
  562. ******************************************************************************/
  563.  
  564. static int Echo_ungetc PARAMS((int c));
  565. static int Echo_getc PARAMS((void));
  566. static int Skip_Spaces PARAMS((void));
  567. static int Parse_C_Comments PARAMS((void));
  568. static void Begin_String PARAMS((void));
  569. static void Stuff_Character PARAMS((int c));
  570. static void End_String PARAMS((void));
  571. static int Read_Float PARAMS((void));
  572. static void Parse_String_Literal PARAMS((void));
  573. static void Read_Symbol PARAMS((void));
  574. static int Find_Reserved PARAMS((char *s, int hash_value));
  575. static int Find_Symbol PARAMS((char *s, int hash_value));
  576. static void Skip_Tokens PARAMS((COND_TYPE cond));
  577.  
  578. static int get_hash_value PARAMS((char *s));
  579. static void init_reserved_words_hash_table PARAMS((void));
  580.  
  581.  
  582.  
  583.  
  584. /*****************************************************************************
  585. *
  586. * FUNCTION
  587. *
  588. * INPUT
  589. *
  590. * OUTPUT
  591. *
  592. * RETURNS
  593. *
  594. * AUTHOR
  595. *
  596. * DESCRIPTION
  597. *
  598. * CHANGES
  599. *
  600. ******************************************************************************/
  601.  
  602. void Initialize_Tokenizer()
  603. {
  604.   int i;
  605.  
  606.   Stage = STAGE_TOKEN_INIT;
  607.  
  608.   pre_init_tokenizer ();
  609.  
  610.   if (!strcmp(opts.Input_File_Name,"-"))
  611.   {
  612.     Data_File->File = stdin;
  613.   }
  614.   else
  615.   {
  616.      if (input_file_in_memory)
  617.      {
  618.         /* Note platforms which use this feature will
  619.          * trap fopen so the NULL is ok [C.Cason 7/3/96]
  620.          */
  621.         Data_File->File = fopen (NULL, "rt") ;
  622.      }
  623.      else
  624.      {
  625.         Data_File->File = Locate_File (opts.Input_File_Name, READ_FILE_STRING,".pov",".POV",TRUE);
  626.      }
  627.   }
  628.  
  629.   if (Data_File->File == NULL)
  630.   {
  631.     Error ("Cannot open input file.");
  632.   }
  633.  
  634.   Data_File->Filename = POV_MALLOC(strlen(opts.Input_File_Name)+1, "filename");
  635.  
  636.   strcpy (Data_File->Filename, opts.Input_File_Name);
  637.  
  638.   Data_File->Line_Number = 0;
  639.  
  640.   /* Allocate constants table. */
  641.  
  642.   Constants = (struct Constant_Struct *)POV_MALLOC((Max_Constants+1) * sizeof (struct Constant_Struct), "constants table");
  643.  
  644.   /* Init echo buffer. */
  645.  
  646.   Echo_Buff = (char **)POV_MALLOC(sizeof(char *) * Num_Echo_Lines, "echo buffer");
  647.  
  648.   for (Echo_Line = 0; Echo_Line < Num_Echo_Lines; Echo_Line++)
  649.   {
  650.     Echo_Buff[Echo_Line] = (char *)POV_MALLOC((size_t)Echo_Line_Length+10, "echo buffer");
  651.  
  652.     Echo_Buff[Echo_Line][0]='\0';
  653.   }
  654.  
  655.   Echo_Line = 0;
  656.   Echo_Ptr = Echo_Buff[0];
  657.  
  658.   /* Init conditional stack. */
  659.  
  660.   Cond_Stack = (CS_ENTRY*)POV_MALLOC(sizeof(CS_ENTRY*) * COND_STACK_SIZE, "conditional stack");
  661.  
  662.   Cond_Stack[0].Cond_Type    = ROOT_COND;
  663.   Cond_Stack[0].Switch_Value = 0.0;
  664.  
  665.   /* Init token hash tables. */
  666.  
  667.   init_reserved_words_hash_table();
  668.  
  669.   for (i = 0; i < HASH_TABLE_SIZE; i++)
  670.   {
  671.     Symbol_Table_Hash_Table[i] = NULL;
  672.   }
  673. }
  674.  
  675.  
  676.  
  677. /*****************************************************************************
  678. *
  679. * FUNCTION
  680. *
  681. * INPUT
  682. *
  683. * OUTPUT
  684. *
  685. * RETURNS
  686. *
  687. * AUTHOR
  688. *
  689. * DESCRIPTION
  690. *
  691. * CHANGES
  692. *
  693. ******************************************************************************/
  694.  
  695. void pre_init_tokenizer ()
  696. {
  697.   Token.Token_Line_No = 0;
  698.   Token.Token_String  = NULL;
  699.   Token.Unget_Token   = FALSE;
  700.   Token.End_Of_File   = FALSE;
  701.   Token.Filename      = NULL;
  702.   Token.Constant_Data = NULL;
  703.  
  704.   Constants = NULL;
  705.   Data_File = NULL;
  706.  
  707.   Number_Of_Constants = 0;
  708.   line_count = 10;
  709.   token_count = 0;
  710.   Include_File_Index = 0;
  711.   Echo_Indx=0;
  712.   Echo_Line=0;
  713.   Echo_Ptr=NULL;
  714.   Echo_Buff=NULL;
  715.   Echo_Unget_Flag=FALSE;
  716.   Echo_Unget_Char='\0';
  717.  
  718.   Number_Of_Symbols = 0;
  719.  
  720.   CS_Index            = 0;
  721.   Skipping            = FALSE;
  722.   Inside_Ifdef        = FALSE;
  723.   Cond_Stack          = NULL;
  724.   Data_File = &Include_Files[0];
  725.   Data_File->Filename = NULL;
  726. }
  727.  
  728.  
  729. /*****************************************************************************
  730. *
  731. * FUNCTION
  732. *
  733. * INPUT
  734. *
  735. * OUTPUT
  736. *
  737. * RETURNS
  738. *
  739. * AUTHOR
  740. *
  741. * DESCRIPTION
  742. *
  743. * CHANGES
  744. *
  745. ******************************************************************************/
  746.  
  747. void Terminate_Tokenizer()
  748. {
  749.   int i;
  750.   HASH_TABLE *p, *temp;
  751.  
  752.   for (i = 0 ; i < HASH_TABLE_SIZE; i++)
  753.   {
  754.     p = Symbol_Table_Hash_Table[i];
  755.  
  756.     while (p)
  757.     {
  758.       temp = p->next;
  759.  
  760.       POV_FREE(p->Entry.Token_Name);
  761.  
  762.       POV_FREE(p);
  763.  
  764.       p = temp;
  765.     }
  766.  
  767.     Symbol_Table_Hash_Table[i] = NULL;
  768.   }
  769.  
  770.   for (i = 0 ; i < HASH_TABLE_SIZE; i++)
  771.   {
  772.     p = Reserved_Words_Hash_Table[i];
  773.  
  774.     while (p)
  775.     {
  776.       temp = p->next;
  777.  
  778.       POV_FREE(p);
  779.  
  780.       p = temp;
  781.     }
  782.  
  783.     Reserved_Words_Hash_Table[i] = NULL;
  784.   }
  785.  
  786.   if (Data_File->File != NULL)
  787.   {
  788.     fclose (Data_File->File);
  789.  
  790.     POV_FREE (Data_File->Filename);
  791.  
  792.     Data_File->File = NULL;
  793.   }
  794.  
  795.   if (Echo_Buff != NULL)
  796.   {
  797.     for (Echo_Line = 0; Echo_Line < Num_Echo_Lines; Echo_Line++)
  798.     {
  799.       if (Echo_Buff[Echo_Line]!=NULL)
  800.       {
  801.         POV_FREE (Echo_Buff[Echo_Line]);
  802.  
  803.         Echo_Buff[Echo_Line]=NULL;
  804.       }
  805.     }
  806.  
  807.     POV_FREE (Echo_Buff);
  808.  
  809.     Echo_Buff = NULL;
  810.   }
  811.  
  812.   if (Cond_Stack!=NULL)
  813.   {
  814.     POV_FREE (Cond_Stack);
  815.  
  816.     Cond_Stack = NULL;
  817.   }
  818. }
  819.  
  820.  
  821.  
  822. /*****************************************************************************
  823. *
  824. * FUNCTION
  825. *
  826. * INPUT
  827. *
  828. * OUTPUT
  829. *
  830. * RETURNS
  831. *
  832. * AUTHOR
  833. *
  834. * DESCRIPTION
  835. *
  836. *   The main tokenizing routine.  Set up the files and continue parsing
  837. *   until the end of file
  838. *
  839. *   Read a token from the input file and store it in the Token variable.
  840. *   If the token is an INCLUDE token, then set the include file name and
  841. *   read another token.
  842. *
  843. *   This function performs most of the work involved in tokenizing.  It
  844. *   reads the first character of the token and decides which function to
  845. *   call to tokenize the rest.  For simple tokens, it simply writes them
  846. *   out to the token buffer.
  847. *
  848. * CHANGES
  849. *
  850. ******************************************************************************/
  851.  
  852. void Get_Token ()
  853. {
  854.   register int c,c2;
  855.  
  856.   if (Token.Unget_Token)
  857.   {
  858.     Token.Unget_Token = FALSE;
  859.  
  860.     return;
  861.   }
  862.  
  863.   if (Token.End_Of_File)
  864.   {
  865.     return;
  866.   }
  867.  
  868.  
  869.   Token.Token_Id = END_OF_FILE_TOKEN;
  870.  
  871.   while (Token.Token_Id == END_OF_FILE_TOKEN)
  872.   {
  873.     Skip_Spaces();
  874.  
  875.     c = Echo_getc();
  876.  
  877.     if (c == EOF)
  878.     {
  879.       if (Include_File_Index == 0)
  880.       {
  881.         if (CS_Index !=0)
  882.           Error("End of file reached but #end expected.");
  883.  
  884.         Token.Token_Id = END_OF_FILE_TOKEN;
  885.  
  886.         Token.End_Of_File = TRUE;
  887.  
  888.         Status_Info("\n");
  889.  
  890.         return;
  891.       }
  892.  
  893.       fclose(Data_File->File); /* added to fix open file buildup JLN 12/91 */
  894.  
  895.       POV_FREE (Data_File->Filename);
  896.  
  897.       Data_File = &Include_Files[--Include_File_Index];
  898.  
  899.       continue;
  900.     }
  901.  
  902.     String[0] = c; /* This isn't necessar but helps debugging */
  903.  
  904.     String[1] = '\0';
  905.  
  906.     String_Index = 0;
  907.  
  908.     switch (c)
  909.     {
  910.       case '\n':
  911.         Data_File->Line_Number++;
  912.         COOPERATE_0
  913.         break;
  914.  
  915.       case '{' :
  916.         Write_Token (LEFT_CURLY_TOKEN, Data_File);
  917.         break;
  918.   
  919.       case '}' :
  920.         Write_Token (RIGHT_CURLY_TOKEN, Data_File);
  921.         break;
  922.   
  923.       case '@' :
  924.         Write_Token (AT_TOKEN, Data_File);
  925.         break;
  926.   
  927.       case '&' :
  928.         Write_Token (AMPERSAND_TOKEN, Data_File);
  929.         break;
  930.   
  931.       case '`' :
  932.         Write_Token (BACK_QUOTE_TOKEN, Data_File);
  933.         break;
  934.   
  935.       case '\\':
  936.         Write_Token (BACK_SLASH_TOKEN, Data_File);
  937.         break;
  938.  
  939.       case '|' :
  940.         Write_Token (BAR_TOKEN, Data_File);
  941.         break;
  942.   
  943.       case ':' :
  944.         Write_Token (COLON_TOKEN, Data_File);
  945.         break;
  946.   
  947.       case ',' :
  948.         Write_Token (COMMA_TOKEN, Data_File);
  949.         break;
  950.   
  951.       case '-' :
  952.         Write_Token (DASH_TOKEN, Data_File);
  953.         break;
  954.   
  955.       case '$' :
  956.         Write_Token (DOLLAR_TOKEN, Data_File);
  957.         break;
  958.   
  959.       case '=' :
  960.         Write_Token (EQUALS_TOKEN, Data_File);
  961.         break;
  962.   
  963.       case '!' :
  964.         c2 = Echo_getc();
  965.         if (c2 == (int)'=')
  966.         {
  967.           Write_Token (REL_NE_TOKEN, Data_File);
  968.         }
  969.         else
  970.         {
  971.           Echo_ungetc(c2);
  972.           Write_Token (EXCLAMATION_TOKEN, Data_File);
  973.         }
  974.         break;
  975.   
  976.       case '#' : 
  977.         Parse_Directive();
  978.         /* Write_Token (HASH_TOKEN, Data_File);*/
  979.         break;
  980.   
  981.       case '^' :
  982.         Write_Token (HAT_TOKEN, Data_File);
  983.         break;
  984.   
  985.       case '<' :
  986.         c2 = Echo_getc();
  987.         if (c2 == (int)'=')
  988.         {
  989.           Write_Token (REL_LE_TOKEN, Data_File);
  990.         }
  991.         else
  992.         {
  993.           Echo_ungetc(c2);
  994.           Write_Token (LEFT_ANGLE_TOKEN, Data_File);
  995.         }
  996.         break;
  997.   
  998.       case '(' :
  999.         Write_Token (LEFT_PAREN_TOKEN, Data_File);
  1000.         break;
  1001.   
  1002.       case '[' :
  1003.         Write_Token (LEFT_SQUARE_TOKEN, Data_File);
  1004.         break;
  1005.   
  1006.       case '%' :
  1007.         Write_Token (PERCENT_TOKEN, Data_File);
  1008.         break;
  1009.   
  1010.       case '+' :
  1011.         Write_Token (PLUS_TOKEN, Data_File);
  1012.         break;
  1013.   
  1014.       case '?' :
  1015.         Write_Token (QUESTION_TOKEN, Data_File);
  1016.         break;
  1017.   
  1018.       case '>' :
  1019.         c2 = Echo_getc();
  1020.         if (c2 == (int)'=')
  1021.         {
  1022.           Write_Token (REL_GE_TOKEN, Data_File);
  1023.         }
  1024.         else
  1025.         {
  1026.           Echo_ungetc(c2);
  1027.           Write_Token (RIGHT_ANGLE_TOKEN, Data_File);
  1028.         }
  1029.         break;
  1030.   
  1031.       case ')' :
  1032.         Write_Token (RIGHT_PAREN_TOKEN, Data_File);
  1033.         break;
  1034.   
  1035.       case ']' :
  1036.         Write_Token (RIGHT_SQUARE_TOKEN, Data_File);
  1037.         break;
  1038.   
  1039.       case ';' : /* Parser doesn't use it, so let's ignore it */
  1040.         /* Write_Token (SEMI_COLON_TOKEN, Data_File); */
  1041.         break;
  1042.   
  1043.       case '\'':
  1044.         Write_Token (SINGLE_QUOTE_TOKEN, Data_File);
  1045.         break;
  1046.   
  1047.         /* enable C++ style commenting */
  1048.       case '/' :
  1049.         c2 = Echo_getc();
  1050.         if(c2 != (int) '/' && c2 != (int) '*')
  1051.         {
  1052.           Echo_ungetc(c2);
  1053.           Write_Token (SLASH_TOKEN, Data_File);
  1054.           break;
  1055.         }
  1056.         if(c2 == (int)'*')
  1057.         {
  1058.           Parse_C_Comments();
  1059.           break;
  1060.         }
  1061.         while((c2 != (int)'\n') && (c2 != (int)'\r'))
  1062.         {
  1063.           c2=Echo_getc();
  1064.           if(c2==EOF)
  1065.           {
  1066.             Echo_ungetc(c2);
  1067.             break;
  1068.           }
  1069.         }
  1070.         Data_File->Line_Number++;
  1071.         COOPERATE_0
  1072.         break;
  1073.  
  1074.       case '*' :
  1075.         Write_Token (STAR_TOKEN, Data_File);
  1076.         break;
  1077.   
  1078.       case '~' :
  1079.         Write_Token (TILDE_TOKEN, Data_File);
  1080.         break;
  1081.   
  1082.       case '"' :
  1083.         Parse_String_Literal ();
  1084.         break;
  1085.   
  1086.       case '0':
  1087.       case '1':
  1088.       case '2':
  1089.       case '3':
  1090.       case '4':
  1091.       case '5':
  1092.       case '6':
  1093.       case '7':
  1094.       case '8':
  1095.       case '9':
  1096.       case '.':
  1097.         Echo_ungetc(c);
  1098.         if (Read_Float () != TRUE)
  1099.           return;
  1100.         break;
  1101.   
  1102.       case 'a':
  1103.       case 'b':
  1104.       case 'c':
  1105.       case 'd':
  1106.       case 'e':
  1107.       case 'f':
  1108.       case 'g':
  1109.       case 'h':
  1110.       case 'i':
  1111.       case 'j':
  1112.       case 'k':
  1113.       case 'l':
  1114.       case 'm':
  1115.       case 'n':
  1116.       case 'o':
  1117.       case 'p':
  1118.       case 'q':
  1119.       case 'r':
  1120.       case 's':
  1121.       case 't':
  1122.       case 'u':
  1123.       case 'v':
  1124.       case 'w':
  1125.       case 'x':
  1126.       case 'y':
  1127.       case 'z':
  1128.   
  1129.       case 'A':
  1130.       case 'B':
  1131.       case 'C':
  1132.       case 'D':
  1133.       case 'E':
  1134.       case 'F':
  1135.       case 'G':
  1136.       case 'H':
  1137.       case 'I':
  1138.       case 'J':
  1139.       case 'K':
  1140.       case 'L':
  1141.       case 'M':
  1142.       case 'N':
  1143.       case 'O':
  1144.       case 'P':
  1145.       case 'Q':
  1146.       case 'R':
  1147.       case 'S':
  1148.       case 'T':
  1149.       case 'U':
  1150.       case 'V':
  1151.       case 'W':
  1152.       case 'X':
  1153.       case 'Y':
  1154.       case 'Z':
  1155.       case '_':
  1156.         Echo_ungetc(c);
  1157.         Read_Symbol ();
  1158.         break;
  1159.       case '\t':
  1160.       case '\r':
  1161.       case '\032':   /* Control Z - EOF on many systems */
  1162.       case '\0':
  1163.         break;
  1164.   
  1165.       default:
  1166.         Error("Illegal character in input file, value is %02x.\n", c);
  1167.         break;
  1168.     }
  1169.   }
  1170.  
  1171.   token_count++;
  1172.  
  1173.   if (token_count > 1000)
  1174.   {
  1175.     token_count = 0;
  1176.  
  1177.     COOPERATE_0
  1178.  
  1179.     Check_User_Abort(FALSE);
  1180.  
  1181.     Status_Info(".");
  1182.  
  1183.     line_count++;
  1184.  
  1185.     if (line_count > 78)
  1186.     {
  1187.       line_count = 0;
  1188.  
  1189.       Status_Info ("\n");
  1190.     }
  1191.   }
  1192. }
  1193.  
  1194.  
  1195.  
  1196. /*****************************************************************************
  1197. *
  1198. * FUNCTION
  1199. *
  1200. * INPUT
  1201. *
  1202. * OUTPUT
  1203. *
  1204. * RETURNS
  1205. *
  1206. * AUTHOR
  1207. *
  1208. * DESCRIPTION
  1209. *
  1210. *   Mark that the token has been put back into the input stream.  The next
  1211. *   call to Get_Token will return the last-read token instead of reading a
  1212. *   new one from the file.
  1213. *
  1214. * CHANGES
  1215. *
  1216. ******************************************************************************/
  1217.  
  1218. void Unget_Token ()
  1219. {
  1220.   Token.Unget_Token = TRUE;
  1221. }
  1222.  
  1223.  
  1224.  
  1225. /*****************************************************************************
  1226. *
  1227. * FUNCTION
  1228. *
  1229. * INPUT
  1230. *
  1231. * OUTPUT
  1232. *
  1233. * RETURNS
  1234. *
  1235. * AUTHOR
  1236. *
  1237. * DESCRIPTION
  1238. *
  1239. *   Skip over spaces in the input file.
  1240. *
  1241. * CHANGES
  1242. *
  1243. ******************************************************************************/
  1244.  
  1245. static int Skip_Spaces ()
  1246. {
  1247.   register int c;
  1248.  
  1249.   while (TRUE)
  1250.   {
  1251.     c = Echo_getc();
  1252.  
  1253.     if (c == EOF)
  1254.     {
  1255.       return (FALSE);
  1256.     }
  1257.  
  1258.     if (!(isspace(c) || c == 0x0A))
  1259.     {
  1260.       break;
  1261.     }
  1262.  
  1263.     if (c == '\n')
  1264.     {
  1265.       Data_File->Line_Number++;
  1266.  
  1267.       COOPERATE_0
  1268.     }
  1269.   }
  1270.  
  1271.   Echo_ungetc(c);
  1272.  
  1273.   return (TRUE);
  1274. }
  1275.  
  1276.  
  1277.  
  1278. /*****************************************************************************
  1279. *
  1280. * FUNCTION
  1281. *
  1282. * INPUT
  1283. *
  1284. * OUTPUT
  1285. *
  1286. * RETURNS
  1287. *
  1288. * AUTHOR
  1289. *
  1290. * DESCRIPTION
  1291. *
  1292. *   C style comments with asterik and slash - CdW 8/91.
  1293. *
  1294. * CHANGES
  1295. *
  1296. ******************************************************************************/
  1297.  
  1298. static int Parse_C_Comments()
  1299. {
  1300.   register int c, c2;
  1301.   int End_Of_Comment;
  1302.  
  1303.   End_Of_Comment = FALSE;
  1304.  
  1305.   while (!End_Of_Comment)
  1306.   {
  1307.     c = Echo_getc();
  1308.  
  1309.     if (c == EOF)
  1310.     {
  1311.       Error ("No */ closing comment found.");
  1312.     }
  1313.  
  1314.     if (c == (int) '\n')
  1315.     {
  1316.       Data_File->Line_Number++;
  1317.  
  1318.       COOPERATE_0
  1319.     }
  1320.  
  1321.     if (c == (int) '*')
  1322.     {
  1323.       c2 = Echo_getc();
  1324.  
  1325.       if (c2 != (int) '/')
  1326.       {
  1327.         Echo_ungetc(c2);
  1328.       }
  1329.       else
  1330.       {
  1331.         End_Of_Comment = TRUE;
  1332.       }
  1333.     }
  1334.  
  1335.     /* Check for and handle nested comments */
  1336.  
  1337.     if (c == (int) '/')
  1338.     {
  1339.       c2 = Echo_getc();
  1340.  
  1341.       if (c2 != (int) '*')
  1342.       {
  1343.         Echo_ungetc(c2);
  1344.       }
  1345.       else
  1346.       {
  1347.         Parse_C_Comments();
  1348.       }
  1349.     }
  1350.   }
  1351.  
  1352.   return (TRUE);
  1353. }
  1354.  
  1355.  
  1356.  
  1357. /* The following routines make it easier to handle strings.  They stuff
  1358.    characters into a string buffer one at a time making all the proper
  1359.    range checks.  Call Begin_String to start, Stuff_Character to put
  1360.    characters in, and End_String to finish.  The String variable contains
  1361.    the final string. */
  1362.  
  1363. /*****************************************************************************
  1364. *
  1365. * FUNCTION
  1366. *
  1367. * INPUT
  1368. *
  1369. * OUTPUT
  1370. *
  1371. * RETURNS
  1372. *
  1373. * AUTHOR
  1374. *
  1375. * DESCRIPTION
  1376. *
  1377. * CHANGES
  1378. *
  1379. ******************************************************************************/
  1380.  
  1381. static void Begin_String()
  1382. {
  1383.   String_Index = 0;
  1384. }
  1385.  
  1386.  
  1387.  
  1388. /*****************************************************************************
  1389. *
  1390. * FUNCTION
  1391. *
  1392. * INPUT
  1393. *
  1394. * OUTPUT
  1395. *
  1396. * RETURNS
  1397. *
  1398. * AUTHOR
  1399. *
  1400. * DESCRIPTION
  1401. *
  1402. * CHANGES
  1403. *
  1404. ******************************************************************************/
  1405.  
  1406. static void Stuff_Character(c)
  1407. int c;
  1408. {
  1409.   if (String_Index < MAX_STRING_INDEX)
  1410.   {
  1411.     String[String_Index++] = (char)c;
  1412.  
  1413.     if (String_Index >= MAX_STRING_INDEX)
  1414.     {
  1415.       Error ("String too long.");
  1416.     }
  1417.   }
  1418. }
  1419.  
  1420.  
  1421.  
  1422. /*****************************************************************************
  1423. *
  1424. * FUNCTION
  1425. *
  1426. * INPUT
  1427. *
  1428. * OUTPUT
  1429. *
  1430. * RETURNS
  1431. *
  1432. * AUTHOR
  1433. *
  1434. * DESCRIPTION
  1435. *
  1436. * CHANGES
  1437. *
  1438. ******************************************************************************/
  1439.  
  1440. static void End_String()
  1441. {
  1442.   Stuff_Character((int)'\0');
  1443. }
  1444.  
  1445.  
  1446.  
  1447. /*****************************************************************************
  1448. *
  1449. * FUNCTION
  1450. *
  1451. * INPUT
  1452. *
  1453. * OUTPUT
  1454. *
  1455. * RETURNS
  1456. *
  1457. * AUTHOR
  1458. *
  1459. * DESCRIPTION
  1460. *
  1461. *   Read a float from the input file and tokenize it as one token. The phase
  1462. *   variable is 0 for the first character, 1 for all subsequent characters
  1463. *   up to the decimal point, 2 for all characters after the decimal
  1464. *   point, 3 for the E+/- and 4 for the exponent.  This helps to insure
  1465. *   that the number is formatted properly. E format added 9/91 CEY
  1466. *
  1467. * CHANGES
  1468. *
  1469. ******************************************************************************/
  1470.  
  1471. static int Read_Float()
  1472. {
  1473.   register int c, Finished, Phase;
  1474.  
  1475.   Finished = FALSE;
  1476.  
  1477.   Phase = 0;
  1478.  
  1479.   Begin_String();
  1480.  
  1481.   while (!Finished)
  1482.   {
  1483.     c = Echo_getc();
  1484.  
  1485.     if (c == EOF)
  1486.     {
  1487.       Error ("Unexpected end of file.");
  1488.     }
  1489.  
  1490.     switch (Phase)
  1491.     {
  1492.       case 0:
  1493.  
  1494.         Phase = 1;
  1495.  
  1496.         if (isdigit(c))
  1497.         {
  1498.           Stuff_Character(c);
  1499.         }
  1500.         else
  1501.         {
  1502.           if (c == '.')
  1503.           {
  1504.             c = Echo_getc();
  1505.  
  1506.             if (c == EOF)
  1507.             {
  1508.               Error ("Unexpected end of file");
  1509.             }
  1510.  
  1511.             if (isdigit(c))
  1512.             {
  1513.               Stuff_Character('0');
  1514.               Stuff_Character('.');
  1515.               Stuff_Character(c);
  1516.  
  1517.               Phase = 2;
  1518.             }
  1519.             else
  1520.             {
  1521.               Echo_ungetc(c);
  1522.  
  1523.               Write_Token (PERIOD_TOKEN, Data_File);
  1524.  
  1525.               return(TRUE);
  1526.             }
  1527.           }
  1528.           else
  1529.           {
  1530.             Error ("Error in decimal number");
  1531.           }
  1532.         }
  1533.  
  1534.         break;
  1535.  
  1536.       case 1:
  1537.         if (isdigit(c))
  1538.         {
  1539.           Stuff_Character(c);
  1540.         }
  1541.         else
  1542.         {
  1543.           if (c == (int) '.')
  1544.           {
  1545.             Stuff_Character(c); Phase = 2;
  1546.           }
  1547.           else
  1548.           {
  1549.             if ((c == 'e') || (c == 'E'))
  1550.             {
  1551.               Stuff_Character(c); Phase = 3;
  1552.             }
  1553.             else
  1554.             {
  1555.               Finished = TRUE;
  1556.             }
  1557.           }
  1558.         }
  1559.  
  1560.         break;
  1561.  
  1562.       case 2:
  1563.  
  1564.         if (isdigit(c))
  1565.         {
  1566.           Stuff_Character(c);
  1567.         }
  1568.         else
  1569.         {
  1570.           if ((c == 'e') || (c == 'E'))
  1571.           {
  1572.             Stuff_Character(c); Phase = 3;
  1573.           }
  1574.           else
  1575.           {
  1576.             Finished = TRUE;
  1577.           }
  1578.         }
  1579.  
  1580.         break;
  1581.  
  1582.       case 3:
  1583.  
  1584.         if (isdigit(c) || (c == '+') || (c == '-'))
  1585.         {
  1586.           Stuff_Character(c); Phase = 4;
  1587.         }
  1588.         else
  1589.         {
  1590.           Finished = TRUE;
  1591.         }
  1592.  
  1593.         break;
  1594.  
  1595.       case 4:
  1596.  
  1597.         if (isdigit(c))
  1598.         {
  1599.           Stuff_Character(c);
  1600.         }
  1601.         else
  1602.         {
  1603.           Finished = TRUE;
  1604.         }
  1605.  
  1606.         break;
  1607.     }
  1608.   }
  1609.  
  1610.   Echo_ungetc(c);
  1611.  
  1612.   End_String();
  1613.  
  1614.   Write_Token (FLOAT_TOKEN, Data_File);
  1615.  
  1616.   if (sscanf (String, DBL_FORMAT_STRING, &Token.Token_Float) == 0)
  1617.   {
  1618.     return (FALSE);
  1619.   }
  1620.  
  1621.   return (TRUE);
  1622. }
  1623.  
  1624.  
  1625.  
  1626. /*****************************************************************************
  1627. *
  1628. * FUNCTION
  1629. *
  1630. * INPUT
  1631. *
  1632. * OUTPUT
  1633. *
  1634. * RETURNS
  1635. *
  1636. * AUTHOR
  1637. *
  1638. * DESCRIPTION
  1639. *
  1640. *   Parse a string from the input file into a token.
  1641. *
  1642. * CHANGES
  1643. *
  1644. ******************************************************************************/
  1645.  
  1646. static void Parse_String_Literal()
  1647. {
  1648.   register int c;
  1649.  
  1650.   Begin_String();
  1651.  
  1652.   while (TRUE)
  1653.   {
  1654.     c = Echo_getc();
  1655.  
  1656.     if (c == EOF)
  1657.     {
  1658.       Error ("No end quote for string.");
  1659.     }
  1660.  
  1661.     if (c == '\\')
  1662.     {
  1663.       switch(c = Echo_getc())
  1664.       {
  1665.         case '\n':
  1666.         case '\r':
  1667.  
  1668.           Error("Unterminated string literal.");
  1669.  
  1670.           break;
  1671.  
  1672.         case '\"':
  1673.  
  1674.           c = 0x22;
  1675.  
  1676.           break;
  1677.  
  1678.         case EOF:
  1679.  
  1680.           Error ("No end quote for string.");
  1681.  
  1682.           break;
  1683.  
  1684.         default:
  1685.  
  1686.           Stuff_Character ('\\');
  1687.       }
  1688.  
  1689.       Stuff_Character (c);
  1690.     }
  1691.     else
  1692.     {
  1693.       if (c != (int) '"')
  1694.       {
  1695.         Stuff_Character (c);
  1696.       }
  1697.       else
  1698.       {
  1699.         break;
  1700.       }
  1701.     }
  1702.   }
  1703.  
  1704.   End_String();
  1705.  
  1706.   Write_Token (STRING_LITERAL_TOKEN, Data_File);
  1707.  
  1708.   Token.Token_String = String;
  1709. }
  1710.  
  1711.  
  1712.  
  1713. /*****************************************************************************
  1714. *
  1715. * FUNCTION
  1716. *
  1717. * INPUT
  1718. *
  1719. * OUTPUT
  1720. *
  1721. * RETURNS
  1722. *
  1723. * AUTHOR
  1724. *
  1725. * DESCRIPTION
  1726. *
  1727. *   Read in a symbol from the input file. Check to see if it is a reserved
  1728. *   word. If it is, write out the appropriate token. Otherwise, write the
  1729. *   symbol out to the symbol table and write out an IDENTIFIER token. An
  1730. *   identifier token is a token whose token number is greater than the
  1731. *   highest reserved word.
  1732. *
  1733. * CHANGES
  1734. *
  1735. ******************************************************************************/
  1736.  
  1737. static void Read_Symbol()
  1738. {
  1739.   register int c, Symbol_Id;
  1740.   register int hash_value;
  1741.   HASH_TABLE *New_Entry;
  1742.  
  1743.   Begin_String();
  1744.  
  1745.   while (TRUE)
  1746.   {
  1747.     c = Echo_getc();
  1748.  
  1749.     if (c == EOF)
  1750.     {
  1751.       Error ("Unexpected end of file.");
  1752.     }
  1753.  
  1754.     if (isalpha(c) || isdigit(c) || c == (int) '_')
  1755.     {
  1756.       Stuff_Character(c);
  1757.     }
  1758.     else
  1759.     {
  1760.       Echo_ungetc(c);
  1761.  
  1762.       break;
  1763.     }
  1764.   }
  1765.  
  1766.   End_String();
  1767.  
  1768.   if (Inside_Ifdef)
  1769.   {
  1770.     Token.Token_Id = IDENTIFIER_TOKEN;
  1771.  
  1772.     return;
  1773.   }
  1774.  
  1775.   /* If its a reserved keyword, write it and return */
  1776.  
  1777.   if ((Symbol_Id = Find_Reserved(String, get_hash_value(String))) != -1)
  1778.   {
  1779.     Write_Token (Symbol_Id, Data_File);
  1780.   }
  1781.   else
  1782.   {
  1783.     if ((Symbol_Id = Find_Symbol(String, get_hash_value(String))) == -1)
  1784.     {
  1785.       /* Here its an unknown symbol. */
  1786.  
  1787.       if (Skipping)
  1788.       {
  1789.         Write_Token(IDENTIFIER_TOKEN, Data_File);
  1790.       }
  1791.       else
  1792.       {
  1793.         Number_Of_Symbols++;
  1794.  
  1795.         /* Add it to the table. */
  1796.  
  1797.         New_Entry = (HASH_TABLE *)POV_MALLOC(sizeof(HASH_TABLE), "hash table entry");
  1798.  
  1799.         New_Entry->Entry.Token_Number = Symbol_Id = Number_Of_Symbols;
  1800.  
  1801.         New_Entry->Entry.Token_Name = POV_MALLOC(strlen(String)+1, "identifier");
  1802.  
  1803.         strcpy(New_Entry->Entry.Token_Name, String);
  1804.  
  1805.         hash_value = get_hash_value(String);
  1806.  
  1807.         New_Entry->next = Symbol_Table_Hash_Table[hash_value];
  1808.  
  1809.         Symbol_Table_Hash_Table[hash_value] = New_Entry;
  1810.       }
  1811.     }
  1812.  
  1813.     Write_Token (LAST_TOKEN + Symbol_Id, Data_File);
  1814.   }
  1815. }
  1816.  
  1817.  
  1818.  
  1819. /*****************************************************************************
  1820. *
  1821. * FUNCTION
  1822. *
  1823. * INPUT
  1824. *
  1825. * OUTPUT
  1826. *
  1827. * RETURNS
  1828. *
  1829. *   int - Index of the token in the reserved words table or -1 if it isn't there.
  1830. *
  1831. * AUTHOR
  1832. *
  1833. * DESCRIPTION
  1834. *
  1835. *   Use a hash table look-up to find a keyword given in the variable String.
  1836. *
  1837. * CHANGES
  1838. *
  1839. ******************************************************************************/
  1840.  
  1841. static int Find_Reserved(s, hash_value)
  1842. char *s;
  1843. int hash_value;
  1844. {
  1845.   HASH_TABLE *p;
  1846.  
  1847.   p = Reserved_Words_Hash_Table[hash_value];
  1848.  
  1849.   while (p)
  1850.   {
  1851.     if (strcmp(s, p->Entry.Token_Name) == 0)
  1852.     {
  1853.       return(p->Entry.Token_Number);
  1854.     }
  1855.  
  1856.     p = p->next;
  1857.   }
  1858.  
  1859.   return(-1);
  1860. }
  1861.  
  1862.  
  1863.  
  1864. /*****************************************************************************
  1865. *
  1866. * FUNCTION
  1867. *
  1868. * INPUT
  1869. *
  1870. * OUTPUT
  1871. *
  1872. * RETURNS
  1873. *
  1874. *   int - Symbol ID, -1 if not found.
  1875. *
  1876. * AUTHOR
  1877. *
  1878. * DESCRIPTION
  1879. *
  1880. *   Use a hash table look-up to find symbol given in string s.
  1881. *
  1882. * CHANGES
  1883. *
  1884. ******************************************************************************/
  1885.  
  1886. static int Find_Symbol(s, hash_value)
  1887. char *s;
  1888. int hash_value;
  1889. {
  1890.   HASH_TABLE *p;
  1891.  
  1892.   p = Symbol_Table_Hash_Table[hash_value];
  1893.  
  1894.   while (p)
  1895.   {
  1896.     if (strcmp(s, p->Entry.Token_Name) == 0)
  1897.     {
  1898.       return(p->Entry.Token_Number);
  1899.     }
  1900.  
  1901.     p = p->next;
  1902.   }
  1903.  
  1904.   return(-1);
  1905. }
  1906.  
  1907.  
  1908.  
  1909. /*****************************************************************************
  1910. *
  1911. * FUNCTION
  1912. *
  1913. * INPUT
  1914. *
  1915. * OUTPUT
  1916. *
  1917. * RETURNS
  1918. *
  1919. * AUTHOR
  1920. *
  1921. * DESCRIPTION
  1922. *
  1923. * CHANGES
  1924. *
  1925. ******************************************************************************/
  1926.  
  1927. static int Echo_getc()
  1928. {
  1929.   register int c;
  1930.  
  1931.   if (Echo_Unget_Flag)
  1932.   {
  1933.     Echo_Unget_Flag = FALSE;
  1934.  
  1935.     return(Echo_Unget_Char);
  1936.   }
  1937.  
  1938.   Echo_Ptr[Echo_Indx++] = c = getc(Data_File->File);
  1939.  
  1940.   if ((Echo_Indx > Echo_Line_Length) || (c == '\n')|| (c == '\r'))
  1941.   {
  1942.     Echo_Ptr[Echo_Indx] = '\0';
  1943.  
  1944.     Echo_Indx = 0;
  1945.  
  1946.     Echo_Line++;
  1947.  
  1948.     if (Echo_Line == Num_Echo_Lines)
  1949.       Echo_Line = 0;
  1950.  
  1951.     Echo_Ptr=Echo_Buff[Echo_Line];
  1952.   }
  1953.  
  1954.   return(c);
  1955. }
  1956.  
  1957.  
  1958.  
  1959. /*****************************************************************************
  1960. *
  1961. * FUNCTION
  1962. *
  1963. * INPUT
  1964. *
  1965. * OUTPUT
  1966. *
  1967. * RETURNS
  1968. *
  1969. * AUTHOR
  1970. *
  1971. * DESCRIPTION
  1972. *
  1973. * CHANGES
  1974. *
  1975. ******************************************************************************/
  1976.  
  1977. static int Echo_ungetc(int c)
  1978. {
  1979.   Echo_Unget_Flag = TRUE;
  1980.  
  1981.   return(Echo_Unget_Char = c);
  1982. }
  1983.  
  1984.  
  1985.  
  1986. /*****************************************************************************
  1987. *
  1988. * FUNCTION
  1989. *
  1990. * INPUT
  1991. *
  1992. * OUTPUT
  1993. *
  1994. * RETURNS
  1995. *
  1996. * AUTHOR
  1997. *
  1998. * DESCRIPTION
  1999. *
  2000. * CHANGES
  2001. *
  2002. ******************************************************************************/
  2003.  
  2004. void Where_Error ()
  2005. {
  2006.   int i;
  2007.  
  2008.   /* Return if no filename is specified. [DB 8/94] */
  2009.  
  2010.   if (Token.Filename == NULL)
  2011.   {
  2012.     return;
  2013.   }
  2014.  
  2015.   strcpy (&(Echo_Ptr[Echo_Indx])," <----ERROR\n");
  2016.  
  2017.   for (i=0;i<Num_Echo_Lines;i++)
  2018.   {
  2019.     Echo_Line++;
  2020.  
  2021.     if (Echo_Line==Num_Echo_Lines)
  2022.     {
  2023.       Echo_Line=0;
  2024.     }
  2025.  
  2026.     Error_Line(Echo_Buff[Echo_Line]);
  2027.   }
  2028.  
  2029.   Error_Line("\n%s:%d: error: ", Token.Filename, Token.Token_Line_No+1);
  2030. }
  2031.  
  2032.  
  2033.  
  2034.  
  2035. /*****************************************************************************
  2036. *
  2037. * FUNCTION    Parse_Directive
  2038. *
  2039. * INPUT
  2040. *
  2041. * OUTPUT
  2042. *
  2043. * RETURNS
  2044. *
  2045. * AUTHOR      Chris Young
  2046. *
  2047. * DESCRIPTION
  2048. *
  2049. * CHANGES
  2050. *
  2051. ******************************************************************************/
  2052.  
  2053. void Parse_Directive()
  2054. {
  2055.   DBL Value, Value2;
  2056.   int Flag;
  2057.   char *ts;
  2058.   COND_TYPE Curr_Type = Cond_Stack[CS_Index].Cond_Type;
  2059.   
  2060.   if (!Ok_To_Declare)
  2061.   {
  2062.     Token.Unget_Token = FALSE;
  2063.  
  2064.     return;
  2065.   }
  2066.  
  2067.   EXPECT
  2068.     CASE(IFDEF_TOKEN)
  2069.       CS_Index++;
  2070.  
  2071.       if (Skipping)
  2072.       {
  2073.         Cond_Stack[CS_Index].Cond_Type = SKIP_TIL_END_COND;
  2074.         Skip_Tokens(SKIP_TIL_END_COND);
  2075.       }
  2076.       else
  2077.       {
  2078.         GET(LEFT_PAREN_TOKEN)
  2079.         Inside_Ifdef=TRUE;
  2080.         Get_Token();
  2081.         strcpy(String2,String);
  2082.         Inside_Ifdef=FALSE;
  2083.         GET(RIGHT_PAREN_TOKEN)
  2084.         
  2085.         if (Find_Symbol(String2, get_hash_value(String2)) != -1)
  2086.         {
  2087.            Cond_Stack[CS_Index].Cond_Type=IF_TRUE_COND;
  2088.         }
  2089.         else
  2090.         {
  2091.            Cond_Stack[CS_Index].Cond_Type=IF_FALSE_COND;
  2092.            Skip_Tokens(IF_FALSE_COND);
  2093.            ALLOW(ELSE_TOKEN);
  2094.            ALLOW(END_TOKEN);
  2095.         }
  2096.       }
  2097.       EXIT
  2098.     END_CASE
  2099.     
  2100.     CASE(IFNDEF_TOKEN)
  2101.       CS_Index++;
  2102.  
  2103.       if (Skipping)
  2104.       {
  2105.         Cond_Stack[CS_Index].Cond_Type = SKIP_TIL_END_COND;
  2106.         Skip_Tokens(SKIP_TIL_END_COND);
  2107.       }
  2108.       else
  2109.       {
  2110.         GET(LEFT_PAREN_TOKEN)
  2111.         Inside_Ifdef=TRUE;
  2112.         Get_Token();
  2113.         strcpy(String2,String);
  2114.         Inside_Ifdef=FALSE;
  2115.         GET(RIGHT_PAREN_TOKEN)
  2116.         
  2117.         if (Find_Symbol(String2, get_hash_value(String2)) != -1)
  2118.         {
  2119.            Cond_Stack[CS_Index].Cond_Type=IF_FALSE_COND;
  2120.            Skip_Tokens(IF_FALSE_COND);
  2121.            ALLOW(ELSE_TOKEN);
  2122.            ALLOW(END_TOKEN);
  2123.         }
  2124.         else
  2125.         {
  2126.            Cond_Stack[CS_Index].Cond_Type=IF_TRUE_COND;
  2127.         }
  2128.       }
  2129.       EXIT
  2130.     END_CASE
  2131.     
  2132.     CASE(IF_TOKEN)
  2133.       CS_Index++;
  2134.  
  2135.       if (Skipping)
  2136.       {
  2137.         Cond_Stack[CS_Index].Cond_Type = SKIP_TIL_END_COND;
  2138.         Skip_Tokens(SKIP_TIL_END_COND);
  2139.       }
  2140.       else
  2141.       {
  2142.         Value=Parse_Float_Param();
  2143.       
  2144.         if (fabs(Value)>EPSILON)
  2145.         {
  2146.            Cond_Stack[CS_Index].Cond_Type=IF_TRUE_COND;
  2147.         }
  2148.         else
  2149.         {
  2150.            Cond_Stack[CS_Index].Cond_Type=IF_FALSE_COND;
  2151.            Skip_Tokens(IF_FALSE_COND);
  2152.            ALLOW(ELSE_TOKEN);
  2153.            ALLOW(END_TOKEN);
  2154.         }
  2155.       }
  2156.       EXIT
  2157.     END_CASE
  2158.  
  2159.  
  2160.     CASE(WHILE_TOKEN)
  2161.       CS_Index++;
  2162.  
  2163.       if (Skipping)
  2164.       {
  2165.         Cond_Stack[CS_Index].Cond_Type = SKIP_TIL_END_COND;
  2166.         Skip_Tokens(SKIP_TIL_END_COND);
  2167.       }
  2168.       else
  2169.       {
  2170.         Cond_Stack[CS_Index].While_File    = Data_File->File;
  2171.         Cond_Stack[CS_Index].While_Pos     = ftell(Data_File->File);
  2172.         Cond_Stack[CS_Index].While_Line_No = Data_File->Line_Number;
  2173.  
  2174.         if (Echo_Unget_Flag)
  2175.         {
  2176.            Cond_Stack[CS_Index].While_Pos--;
  2177.         }
  2178.  
  2179.         Value=Parse_Float_Param();
  2180.        
  2181.         if (fabs(Value)>EPSILON)
  2182.         {
  2183.            Cond_Stack[CS_Index].Cond_Type = WHILE_COND;
  2184.         }
  2185.         else
  2186.         {
  2187.            Cond_Stack[CS_Index].Cond_Type = SKIP_TIL_END_COND;
  2188.            Skip_Tokens(SKIP_TIL_END_COND);
  2189.         }
  2190.       }
  2191.       EXIT
  2192.     END_CASE
  2193.     
  2194.  
  2195.     CASE(ELSE_TOKEN)
  2196.       switch (Curr_Type)
  2197.       {
  2198.          case IF_TRUE_COND:
  2199.            Cond_Stack[CS_Index].Cond_Type = ELSE_COND;
  2200.            Skip_Tokens(ELSE_COND);
  2201.            break;
  2202.            
  2203.          case IF_FALSE_COND:
  2204.            Cond_Stack[CS_Index].Cond_Type = ELSE_COND;
  2205.            UNGET
  2206.            break;
  2207.          
  2208.          case CASE_TRUE_COND:
  2209.          case SKIP_TIL_END_COND:
  2210.            break;
  2211.  
  2212.          case CASE_FALSE_COND:
  2213.            Cond_Stack[CS_Index].Cond_Type = CASE_TRUE_COND;
  2214.            if (Skipping)
  2215.            {
  2216.               Token.Token_Id=HASH_TOKEN; /*insures Skip_Token takes notice*/
  2217.               UNGET
  2218.            }
  2219.            break;
  2220.  
  2221.          default:
  2222.            Error("Mis-matched '#else'.");
  2223.       }
  2224.       EXIT
  2225.     END_CASE
  2226.  
  2227.     CASE(SWITCH_TOKEN)
  2228.       CS_Index++;
  2229.  
  2230.       if (Skipping)
  2231.       {
  2232.         Cond_Stack[CS_Index].Cond_Type = SKIP_TIL_END_COND;
  2233.         Skip_Tokens(SKIP_TIL_END_COND);
  2234.       }
  2235.       else
  2236.       {
  2237.         Cond_Stack[CS_Index].Switch_Value=Parse_Float_Param();
  2238.         Cond_Stack[CS_Index].Cond_Type=SWITCH_COND;
  2239.         EXPECT
  2240.           CASE2(CASE_TOKEN,RANGE_TOKEN)
  2241.             if (Token.Token_Id==CASE_TOKEN)
  2242.             {
  2243.               Value=Parse_Float_Param();
  2244.               Flag = (fabs(Value-Cond_Stack[CS_Index].Switch_Value)<EPSILON);
  2245.             }
  2246.             else
  2247.             {
  2248.               Parse_Float_Param2(&Value,&Value2);
  2249.               Flag = ((Cond_Stack[CS_Index].Switch_Value >= Value) &&
  2250.                       (Cond_Stack[CS_Index].Switch_Value <= Value2));
  2251.             }
  2252.  
  2253.             if(Flag)
  2254.             {
  2255.               Cond_Stack[CS_Index].Cond_Type=CASE_TRUE_COND;
  2256.             }
  2257.             else
  2258.             {
  2259.               Cond_Stack[CS_Index].Cond_Type=CASE_FALSE_COND;
  2260.               Skip_Tokens(CASE_FALSE_COND);
  2261.             }
  2262.             EXIT
  2263.           END_CASE
  2264.  
  2265.           OTHERWISE
  2266.             Error("#switch not followed by #case or #range.");
  2267.           END_CASE
  2268.         END_EXPECT
  2269.       }
  2270.     END_CASE
  2271.  
  2272.     CASE(BREAK_TOKEN)
  2273.       if (Curr_Type==CASE_TRUE_COND)
  2274.       {
  2275.         Cond_Stack[CS_Index].Cond_Type=SKIP_TIL_END_COND;
  2276.         Skip_Tokens(SKIP_TIL_END_COND);
  2277.       }          
  2278.       EXIT
  2279.     END_CASE
  2280.     
  2281.     CASE2(CASE_TOKEN,RANGE_TOKEN)
  2282.       switch(Curr_Type)
  2283.       {
  2284.         case CASE_TRUE_COND:
  2285.         case CASE_FALSE_COND:
  2286.           if (Token.Token_Id==CASE_TOKEN)
  2287.           {
  2288.             Value=Parse_Float_Param();
  2289.             Flag = (fabs(Value-Cond_Stack[CS_Index].Switch_Value)<EPSILON);
  2290.           }
  2291.           else
  2292.           {
  2293.             Parse_Float_Param2(&Value,&Value2);
  2294.             Flag = ((Cond_Stack[CS_Index].Switch_Value >= Value) &&
  2295.                     (Cond_Stack[CS_Index].Switch_Value <= Value2));
  2296.           }
  2297.           
  2298.           if(Flag && (Curr_Type==CASE_FALSE_COND))
  2299.           {
  2300.             Cond_Stack[CS_Index].Cond_Type=CASE_TRUE_COND;
  2301.             if (Skipping)
  2302.             {
  2303.                Token.Token_Id=HASH_TOKEN; /*insures Skip_Token takes notice*/
  2304.                UNGET
  2305.             }
  2306.           }
  2307.           break;           
  2308.  
  2309.         case SWITCH_COND:
  2310.           UNGET
  2311.         case SKIP_TIL_END_COND:
  2312.           break;
  2313.  
  2314.         default:
  2315.           Error("Mis-matched '#case' or '#range'.");
  2316.       }
  2317.       EXIT
  2318.     END_CASE
  2319.     
  2320.     CASE(END_TOKEN)
  2321.       switch (Curr_Type)
  2322.       {
  2323.          case IF_FALSE_COND:
  2324.            UNGET
  2325.          case IF_TRUE_COND:
  2326.          case ELSE_COND:
  2327.          case CASE_TRUE_COND:
  2328.          case CASE_FALSE_COND:
  2329.          case SKIP_TIL_END_COND:
  2330.            if (--CS_Index < 0)
  2331.            {
  2332.               Error("Mis-matched '#end'.");
  2333.            }
  2334.            if (Skipping)
  2335.            {
  2336.               Token.Token_Id=HASH_TOKEN; /*insures Skip_Token takes notice*/
  2337.               UNGET
  2338.            }
  2339.            EXIT
  2340.            break;
  2341.          
  2342.          case WHILE_COND:
  2343.            if (Cond_Stack[CS_Index].While_File != Data_File->File)
  2344.            { 
  2345.               Error("#while loop didn't end in file where it started.");
  2346.            }
  2347.            
  2348.            if (fseek(Data_File->File, Cond_Stack[CS_Index].While_Pos,0) < 0)
  2349.            {
  2350.               Error("Unable to seek in input file for #while directive.\n");
  2351.            }
  2352.  
  2353.            Data_File->Line_Number = Cond_Stack[CS_Index].While_Line_No;
  2354.  
  2355.            Value=Parse_Float_Param();
  2356.       
  2357.            if (fabs(Value)<EPSILON)
  2358.            {
  2359.              Cond_Stack[CS_Index].Cond_Type = SKIP_TIL_END_COND;
  2360.              Skip_Tokens(SKIP_TIL_END_COND);
  2361.            }
  2362.            break;
  2363.  
  2364.          default:
  2365.            Error("Mis-matched '#end'.");
  2366.       }
  2367.     END_CASE
  2368.  
  2369.     CASE (DECLARE_TOKEN)
  2370.       if (Skipping)
  2371.       {
  2372.          UNGET
  2373.          EXIT
  2374.       }
  2375.       else
  2376.       {
  2377.          Parse_Declare ();
  2378.          Get_Token ();
  2379.          Unget_Token ();
  2380.       }
  2381.     END_CASE
  2382.     
  2383.     CASE (DEFAULT_TOKEN)
  2384.       Parse_Default();
  2385.       EXIT
  2386.     END_CASE
  2387.  
  2388.     CASE (INCLUDE_TOKEN)
  2389.       if (Skipping)
  2390.       {
  2391.         UNGET
  2392.         EXIT
  2393.       }
  2394.       else
  2395.       {
  2396.         Open_Include();
  2397.         Get_Token ();
  2398.         Unget_Token ();
  2399.       }
  2400.     END_CASE
  2401.  
  2402.     CASE (FLOAT_FUNCT_TOKEN)
  2403.       if (Skipping)
  2404.       {
  2405.         UNGET
  2406.         EXIT
  2407.       }
  2408.       else
  2409.       {
  2410.         switch(Token.Function_Id)
  2411.         {
  2412.            case VERSION_TOKEN:
  2413.              Ok_To_Declare = FALSE;
  2414.              opts.Language_Version = Parse_Float ();
  2415.              Ok_To_Declare = TRUE;
  2416.              break;
  2417.  
  2418.            default:
  2419.              UNGET
  2420.              Parse_Error_Str ("object or directive.");
  2421.              break;
  2422.         }
  2423.       }
  2424.     END_CASE
  2425.  
  2426.     CASE(WARNING_TOKEN)
  2427.       if (Skipping)
  2428.       {
  2429.         UNGET
  2430.         EXIT
  2431.       }
  2432.       else
  2433.       {     
  2434.         ts=Parse_Formatted_String();
  2435.         Warning(0.0,ts);
  2436.         POV_FREE(ts);
  2437.       }
  2438.     END_CASE
  2439.       
  2440.     CASE(ERROR_TOKEN)
  2441.       if (Skipping)
  2442.       {
  2443.         UNGET
  2444.         EXIT
  2445.       }
  2446.       else
  2447.       {     
  2448.         ts=Parse_Formatted_String();
  2449.         POV_FREE(ts);
  2450.         Error("User error directive hit.");
  2451.       }
  2452.     END_CASE
  2453.       
  2454.     CASE(RENDER_TOKEN)
  2455.       if (Skipping)
  2456.       {
  2457.         UNGET
  2458.         EXIT
  2459.       }
  2460.       else
  2461.       {     
  2462.         ts=Parse_Formatted_String();
  2463.         Render_Info(ts);
  2464.         POV_FREE(ts);
  2465.       }
  2466.     END_CASE
  2467.       
  2468.     CASE(STATISTICS_TOKEN)
  2469.       if (Skipping)
  2470.       {
  2471.         UNGET
  2472.         EXIT
  2473.       }
  2474.       else
  2475.       {     
  2476.         ts=Parse_Formatted_String();
  2477.         Statistics(ts);
  2478.         POV_FREE(ts);
  2479.       }
  2480.     END_CASE
  2481.       
  2482.     CASE(DEBUG_TOKEN)
  2483.       if (Skipping)
  2484.       {
  2485.         UNGET
  2486.         EXIT
  2487.       }
  2488.       else
  2489.       {     
  2490.         ts=Parse_Formatted_String();
  2491.         Debug_Info(ts);
  2492.         POV_FREE(ts);
  2493.       }
  2494.     END_CASE
  2495.  
  2496.     OTHERWISE
  2497.       UNGET
  2498.       EXIT
  2499.     END_CASE
  2500.   END_EXPECT
  2501.   
  2502.   if (Token.Unget_Token)
  2503.   {
  2504.     Token.Unget_Token = FALSE;
  2505.   }
  2506.   else
  2507.   {
  2508.     Token.Token_Id = END_OF_FILE_TOKEN;
  2509.   }
  2510. }
  2511.  
  2512.  
  2513.  
  2514. /*****************************************************************************
  2515. *
  2516. * FUNCTION
  2517. *
  2518. * INPUT
  2519. *
  2520. * OUTPUT
  2521. *
  2522. * RETURNS
  2523. *
  2524. * AUTHOR
  2525. *
  2526. * DESCRIPTION
  2527. *
  2528. * CHANGES
  2529. *
  2530. ******************************************************************************/
  2531.  
  2532. void Open_Include()
  2533. {
  2534.    char *temp;
  2535.  
  2536.    if (Skip_Spaces () != TRUE)
  2537.      Error ("Expecting a string after INCLUDE.\n");
  2538.  
  2539.    Include_File_Index++;
  2540.  
  2541.    if (Include_File_Index > MAX_INCLUDE_FILES)
  2542.      Error ("Too many nested include files.\n");
  2543.  
  2544.    temp = Parse_String();
  2545.  
  2546.    Data_File = &Include_Files[Include_File_Index];
  2547.    Data_File->Line_Number = 0;
  2548.    Data_File->Filename = temp;
  2549.  
  2550.    if ((Data_File->File = Locate_File (Data_File->Filename, READ_FILE_STRING,".inc",".INC",TRUE)) == NULL)
  2551.    {
  2552.       Stage=STAGE_INCLUDE_ERR;
  2553.       Error ("Cannot open include file %s.\n", Data_File->Filename);
  2554.    }
  2555.  
  2556.    Token.Token_Id = END_OF_FILE_TOKEN;
  2557. }
  2558.  
  2559.  
  2560.  
  2561. /*****************************************************************************
  2562. *
  2563. * FUNCTION
  2564. *
  2565. * INPUT
  2566. *
  2567. * OUTPUT
  2568. *
  2569. * RETURNS
  2570. *
  2571. * AUTHOR
  2572. *
  2573. * DESCRIPTION
  2574. *
  2575. * CHANGES
  2576. *
  2577. ******************************************************************************/
  2578.  
  2579. static void Skip_Tokens(cond)
  2580. COND_TYPE cond;
  2581. {
  2582.   int Temp      = CS_Index;
  2583.   int Prev_Skip = Skipping;
  2584.  
  2585.   Skipping=TRUE;
  2586.  
  2587.   while ((CS_Index > Temp) || ((CS_Index == Temp) && (Cond_Stack[CS_Index].Cond_Type == cond)))
  2588.   {
  2589.     Get_Token();
  2590.   }
  2591.  
  2592.   Skipping=Prev_Skip;
  2593.  
  2594.   if (Token.Token_Id==HASH_TOKEN)
  2595.   {
  2596.     Get_Token();
  2597.   }
  2598.  
  2599.   UNGET
  2600. }
  2601.  
  2602.  
  2603.  
  2604. /*****************************************************************************
  2605. *
  2606. * FUNCTION
  2607. *
  2608. *   get_hash_value
  2609. *
  2610. * INPUT
  2611. *
  2612. * OUTPUT
  2613. *
  2614. * RETURNS
  2615. *
  2616. * AUTHOR
  2617. *
  2618. *   Dieter Bayer
  2619. *
  2620. * DESCRIPTION
  2621. *
  2622. *   Calculate hash value for a given string.
  2623. *
  2624. * CHANGES
  2625. *
  2626. *   Apr 1996 : Creation.
  2627. *
  2628. ******************************************************************************/
  2629.  
  2630. static int get_hash_value(s)
  2631. char *s;
  2632. {
  2633.   unsigned int i = 0;
  2634.  
  2635.   while (*s)
  2636.   {
  2637.     i = (i << 1) ^ *s++;
  2638.   }
  2639.  
  2640.   return((int)(i % HASH_TABLE_SIZE));
  2641. }
  2642.  
  2643.  
  2644.  
  2645. /*****************************************************************************
  2646. *
  2647. * FUNCTION
  2648. *
  2649. *   init_reserved_words_hash_table
  2650. *
  2651. * INPUT
  2652. *
  2653. * OUTPUT
  2654. *
  2655. * RETURNS
  2656. *
  2657. * AUTHOR
  2658. *
  2659. *   Dieter Bayer
  2660. *
  2661. * DESCRIPTION
  2662. *
  2663. *   Sort token list.
  2664. *
  2665. * CHANGES
  2666. *
  2667. *   Apr 1996 : Creation.
  2668. *
  2669. ******************************************************************************/
  2670.  
  2671. static void init_reserved_words_hash_table()
  2672. {
  2673.   int i;
  2674.   unsigned int hash_value;
  2675.   HASH_TABLE *New_Entry;
  2676.  
  2677.   for (i = 0; i < HASH_TABLE_SIZE; i++)
  2678.   {
  2679.     Reserved_Words_Hash_Table[i] = NULL;
  2680.   }
  2681.  
  2682.   for (i = 0; i < LAST_TOKEN; i++)
  2683.   {
  2684.     hash_value = get_hash_value(Reserved_Words[i].Token_Name);
  2685.  
  2686.     New_Entry = (HASH_TABLE *)POV_MALLOC(sizeof(HASH_TABLE), "hash table entry");
  2687.  
  2688.     New_Entry->Entry = Reserved_Words[i];
  2689.  
  2690.     New_Entry->next = Reserved_Words_Hash_Table[hash_value];
  2691.  
  2692.     Reserved_Words_Hash_Table[hash_value] = New_Entry;
  2693.   }
  2694. }
  2695.  
  2696.